package org.csu.chatserver.handlerDispatcher;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.stream.ChunkedFile;
import org.csu.chatserver.msg.MessageData;
import org.csu.chatserver.msg.MetaData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;

public class FileHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

    private RandomAccessFile writingFile;
    private String currentFileName;
    private long expectedFileSize;
    private long receivedSize = 0;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame Frame) throws Exception {
        if (Frame instanceof TextWebSocketFrame msg) {
            String received = msg.text();
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                // 1. 将JSON解析为通用树模型
                JsonNode rootNode = objectMapper.readTree(received);
                // 2. 获取类型字段
                String type = rootNode.get("type").asText();
                if (type.equals("FILE_UPLOAD")) {
                    MetaData metaData = objectMapper.readValue(received, MetaData.class);
                    handleMetadata(ctx, metaData);
                }else {
                    ctx.fireChannelRead(msg.retain());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (Frame instanceof BinaryWebSocketFrame) {
            handleFileChunk(ctx, Frame.content());
        }
    }

    private void handleFileChunk(ChannelHandlerContext ctx, ByteBuf buffer) {
        if (writingFile == null) {
            String errorMsg = String.format("{\"responseMsg\":\"file_meta\"}");
            ctx.writeAndFlush(new TextWebSocketFrame(Unpooled.copiedBuffer(errorMsg, StandardCharsets.UTF_8)));
            return;
        }

        System.out.println("处理文件");
        try {
            byte[] bytes = new byte[buffer.readableBytes()];
            buffer.readBytes(bytes);
            writingFile.write(bytes);
            receivedSize += bytes.length;

            // 完成处理
            if (receivedSize >= expectedFileSize) {
                writingFile.close();
                System.out.println("文件写入完成");
                // 重置状态
                writingFile = null;
                currentFileName = null;
                expectedFileSize = 0;
                receivedSize = 0;
            }
        } catch (IOException e) {
            System.out.println("文件写入失败");
            // 重置状态
            writingFile = null;
            currentFileName = null;
            expectedFileSize = 0;
            receivedSize = 0;
        }
    }

    private void handleMetadata(ChannelHandlerContext ctx, MetaData metaData) {
        try {
            System.out.println("初始化文件写入");
            // 初始化文件写入
            String uploadDir = "/home/molidis/Desktop/";//  文件直接存储在D盘下
            currentFileName = uploadDir + metaData.getFileName();
            expectedFileSize = metaData.getFileSize();
            receivedSize = 0;
            writingFile = new RandomAccessFile(currentFileName, "rw");

            System.out.println("开始请求文件");
            // 开始请求文件
            String fileInfo = String.format("{\"responseMsg\":\"file_meta\",\"fileName\":\"%s\",\"fileSize\":%d}", currentFileName, expectedFileSize);
            ctx.writeAndFlush(new TextWebSocketFrame(Unpooled.copiedBuffer(fileInfo, StandardCharsets.UTF_8)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}